package com.calvin.study.multithread.threadutils;

import java.util.concurrent.CountDownLatch;

/**
 * CountDownLatch（倒数闩） 是一个非常实用的等待多线程并发的工具类。 调用线程可以在倒数闩上进行等待， 一直等待倒数闩的次数减少到0，
 * 才继续往下执行。 每一个被等线程执行完成之后进行一次倒数。 所有的被等线程执行完成之后，
 * 倒数闩的次数减少到0，调用线程可以往下执行，从而达到并发等待的效果。
 */

public class CountDownLatchDemo02 {

	public static class NotSafePlus {

		private Integer amount = 0;

		public void selfPlus() {
			amount++;
		}

		public Integer getAmount() {
			return amount;
		}
	}
	
	public static class SafePlus {

		private Integer amount = 0;

		public synchronized void selfPlus() {
			amount++;
		}

		public Integer getAmount() {
			return amount;
		}
	}

	public static class PlusTest {
		final static int MAX_TREAD = 10;
		final static int MAX_TURN = 1000;

		public static void main(String[] args) throws InterruptedException {
			// 倒数闩， 等待10个线程执行完成。
			CountDownLatch latch = new CountDownLatch(MAX_TREAD);

			SafePlus counter = new SafePlus();

			// 10个线程并行运行， 对一个共享数据进行自增运算， 每个线程自增运算1000次
			for (int i = 0; i < MAX_TREAD; i++) {
				new Thread(() -> {
					// 每个线程自增1000次
					for (int j = 0; j < MAX_TURN; j++) {
						counter.selfPlus();
					}
					latch.countDown(); // 倒数闩减少一次
				}).start();
			}

			latch.await(); // 等待倒数闩的次数减少到0， 所有的线程执行完成
			System.out.println("理论结果： " + MAX_TURN * MAX_TREAD);
			System.out.println("实际结果： " + counter.getAmount());
			System.out.println("差距是： " + (MAX_TURN * MAX_TREAD - counter.getAmount()));
		}
	}

}
